package com.ihr360.oneclick.service.impl;

import com.ihr360.commons.lang.DateUtils;
import com.ihr360.oneclick.constant.DtoFieldName;
import com.ihr360.oneclick.dao.StaffRecordDao;
import com.ihr360.oneclick.dto.StaffRecordDto;
import com.ihr360.oneclick.dto.UserStaffRecordDto;
import com.ihr360.oneclick.entity.StaffRecord;
import com.ihr360.oneclick.exception.OneClickException;
import com.ihr360.oneclick.request.SearchRequest;
import com.ihr360.oneclick.request.query.StaffRecordQueryParam;
import com.ihr360.oneclick.service.StaffRecordService;
import com.ihr360.oneclick.util.BeanConvertUtils;
import com.ihr360.oneclick.util.PageableUtils;
import com.ihr360.oneclick.vo.PageData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author tom
 * @date 17-12-20
 */
@Service
public class StaffRecordServiceImpl implements StaffRecordService {

    @Autowired
    private StaffRecordDao staffRecordDao;

    private Specification<StaffRecordDto> buildSpecification(String userId, String companyId, StaffRecordQueryParam queryParam) {
        return (root, cq, cb) -> {
            Predicate predicate = cb.conjunction();
            List<Expression<Boolean>> expressionList = predicate.getExpressions();
            expressionList.add(cb.equal(root.<String>get(DtoFieldName.StaffRecord.COMPANY_ID), companyId));
            expressionList.add(cb.equal(root.<String>get(DtoFieldName.StaffRecord.COMPANY_ID), companyId));
            if (!StringUtils.isEmpty(userId)) {
                Join<StaffRecordDto, UserStaffRecordDto> join = root.join("userStaffRecordList", JoinType.INNER);
                Path<String> userIdPath = join.get("userId");
                expressionList.add(cb.equal(userIdPath, userId));
            }
            if(queryParam != null) {
                if (!StringUtils.isEmpty(queryParam.getLikeStaffName())) {
                    expressionList.add(cb.like(root.<String>get(DtoFieldName.StaffRecord.STAFF_NAME), "%"+ queryParam.getLikeStaffName() + "%"));
                }
                if (!StringUtils.isEmpty(queryParam.getLikeMobileNo())) {
                    expressionList.add(cb.like(root.<String>get(DtoFieldName.StaffRecord.MOBILE_NO), "%"+ queryParam.getLikeMobileNo() + "%"));
                }
                if (!StringUtils.isEmpty(queryParam.getLikeIdCardNo())) {
                    expressionList.add(cb.like(root.<String>get(DtoFieldName.StaffRecord.ID_CARD_NO), "%"+ queryParam.getLikeIdCardNo() + "%"));
                }
                if (!StringUtils.isEmpty(queryParam.getEqIdCardType())) {
                    expressionList.add(cb.equal(root.<String>get(DtoFieldName.StaffRecord.ID_CARD_TYPE), queryParam.getEqIdCardType()));
                }
                if (!StringUtils.isEmpty(queryParam.getGtEnrollInDate())) {
                    expressionList.add(cb.greaterThanOrEqualTo(root.<Date>get(DtoFieldName.StaffRecord.ENTRY_DATE), DateUtils.getMinDateInDay(queryParam.getGtEnrollInDate())));
                }
                if (!StringUtils.isEmpty(queryParam.getLtEnrollInDate())) {
                    expressionList.add(cb.lessThanOrEqualTo(root.<Date>get(DtoFieldName.StaffRecord.ENTRY_DATE), DateUtils.getMaxDateInDay(queryParam.getLtEnrollInDate())));
                }
                if (!StringUtils.isEmpty(queryParam.getSearchParam())) {
                    String search = '%' + queryParam.getSearchParam().trim() + '%';
                    Predicate predicate1 = cb.disjunction();
                    predicate1.getExpressions().add(cb.like(root.<String>get(DtoFieldName.StaffRecord.STAFF_NAME), search));
                    predicate1.getExpressions().add(cb.like(root.<String>get(DtoFieldName.StaffRecord.MOBILE_NO), search));
                    predicate1.getExpressions().add(cb.like(root.<String>get(DtoFieldName.StaffRecord.ID_CARD_NO), search));
                    return cb.and(predicate, predicate1);
                }
            }
            return predicate;
        };
    }

    @Override
    public PageData<StaffRecord> getPageData(String userId, String companyId, SearchRequest searchRequest) {
        Page<StaffRecordDto> page = staffRecordDao.findAll(buildSpecification(userId, companyId, (StaffRecordQueryParam) searchRequest.getQueryParam()),
                PageableUtils.generatePageable(searchRequest));
        PageData<StaffRecord> pageData = new PageData<>(page);
        pageData.setContent(buildStaffRecordList(page.getContent()));
        return pageData;
    }

    @Override
    public List<StaffRecord> getAllData(String companyId, SearchRequest searchRequest) {
        return buildStaffRecordList(staffRecordDao.findAll(buildSpecification(null, companyId, (StaffRecordQueryParam) searchRequest.getQueryParam())));
    }


    @Override
    public StaffRecord getStaffRecordById(String companyId, String staffRecordId) {
        StaffRecordDto staffRecordDto = staffRecordDao.findOne(staffRecordId);
        return BeanConvertUtils.convertFor(staffRecordDto, new StaffRecord());
    }

    private List<StaffRecord> buildStaffRecordList(List<StaffRecordDto> staffListDtoList) {
        List<StaffRecord> staffListList = new ArrayList<>();
        if (CollectionUtils.isEmpty(staffListDtoList)) {
            return staffListList;
        }
        staffListDtoList.forEach(staffListDto ->
            staffListList.add(BeanConvertUtils.convertFor(staffListDto, new StaffRecord()))
        );
        return staffListList;
    }

    @Override
    public List<StaffRecord> getCompanyAllStaffRecord(String companyId) {
        List<StaffRecordDto> staffRecordDtoList = staffRecordDao.findByCompanyId(companyId);
        return buildStaffRecordList(staffRecordDtoList);
    }

    @Override
    public List<StaffRecord> getList(String companyId, List<String> staffRecordIdList) {
        List<StaffRecordDto> staffRecordDtoList = staffRecordDao.findByCompanyIdAndIdIn(companyId, staffRecordIdList);
        return buildStaffRecordList(staffRecordDtoList);
    }

    @Override
    public StaffRecord getStaffRecordByCompanyIdAndMobileNo(String companyId, String mobileNo) {
        StaffRecordDto staffRecordDto = staffRecordDao.findByCompanyIdAndMobileNo(companyId, mobileNo);
        if (staffRecordDto == null) {
            return null;
        }
        return BeanConvertUtils.convertFor(staffRecordDto, new StaffRecord());
    }

    @Override
    public Boolean updateAllow(String companyId, String StaffRecordId, boolean allow) {
        StaffRecordDto StaffRecordDto = staffRecordDao.findByCompanyIdAndId(companyId, StaffRecordId);
        if (StaffRecordDto == null) {
            throw new OneClickException("one_click_spreadsheet_data_error", "数据有误！");
        }
        StaffRecordDto.setAllow(allow);
        StaffRecordDto.setUpdatedAt(new Date());
        staffRecordDao.save(StaffRecordDto);
        return StaffRecordDto.getAllow();
    }

    @Override
    public Boolean updateAllowBatch(String companyId, List<String> StaffRecordIdList, boolean allow) {
        List<StaffRecordDto> StaffRecordDtoList = staffRecordDao.findByCompanyIdAndIdIn(companyId, StaffRecordIdList);
        if (CollectionUtils.isEmpty(StaffRecordDtoList)) {
            throw new OneClickException("one_click_spreadsheet_data_error", "数据有误！");
        }
        StaffRecordDtoList.forEach(StaffRecordDto ->
                StaffRecordDto.setAllow(allow)
        );
        staffRecordDao.save(StaffRecordDtoList);
        return allow;
    }
}
